package com.lagou.rpc.handler;

import com.alibaba.fastjson.JSONObject;
import com.lagou.common.RpcRequest;
import com.lagou.common.RpcResponse;
import com.lagou.rpc.annotation.RpcService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName RpcHandler
 * @Description
 * @Author playboy
 * @Date 2021/6/5 3:13 下午
 * @Version 1.0
 **/
@Component
@ChannelHandler.Sharable
public class RpcHandler extends SimpleChannelInboundHandler<String> implements ApplicationContextAware {

	/**
	 * 用来存放所有被RpcService注解注释的类的接口名与类之间对应关系
	 */
	private ConcurrentHashMap<String, Object> beans = new ConcurrentHashMap<>();

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
		Channel channel = ctx.channel();
		SocketAddress socketAddress = channel.localAddress();
		System.out.println("当前地址：" + socketAddress.toString() + "接受到消息：" + s);

		//将消息转换
		RpcRequest rpcRequest = JSONObject.parseObject(s, RpcRequest.class);
		RpcResponse rpcResponse = new RpcResponse();
		rpcResponse.setResponseId(rpcRequest.getRequestId());
		//handle(rpcRequest);
		Object o = beans.get(rpcRequest.getClassName());
		if (o != null) {
			//可以查询到要调用的类
			Method method = o.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
			Object invoke = method.invoke(o, rpcRequest.getParameters());
			rpcResponse.setResult(invoke);
		} else {
			rpcResponse.setError("没有查询到对应的实体类");
		}
		ctx.writeAndFlush(JSONObject.toJSONString(rpcResponse));
	}

	/**
	 * 容器初始化完成之后
	 *
	 * @param applicationContext
	 * @throws BeansException
	 */
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(RpcService.class);
		for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
			Class<?> anInterface = entry.getValue().getClass().getInterfaces()[0];
			beans.put(anInterface.getName(), entry.getValue());
		}
	}
}
